#ifndef __SOC_FLASH_H__
#define __SOC_FLASH_H__

#include "iperipheral.h"


/// @brief FLASH操作
///        由于内部FLASH一般是存储配置数据(数据量少)，并且有的内部FLASH，扇区很大，不方便写入前回读数据
//         1、所以这里不做字节任意写入
//         2、写入前一定会擦除，所以旧的数据会丢失
//         3、写入的数据，必需保证在一个扇区内
class SOC_Flash : public IPeripheral
{
public:
    static void SetBaseAddress(uint32_t address);
    
    static bool Write(uint32_t address, uint8_t *buf, int length);
    static bool Read(uint32_t address, uint8_t *buf, int length);   

    template<typename T>
    static bool Write(uint32_t address, const T& value)
    {
        return Write(address, (uint8_t *)&value, sizeof(T));
    }

    template<typename T>
    static bool Read(uint32_t address, T& value)
    {
        return Read(address, (uint8_t *)&value, sizeof(T));
    }

    static uint32_t GetSpaceSize(uint32_t startAddress);
    static uint32_t GetSpaceSizeByBaseAddress();

    static uint32_t GetFlashSize();
    static uint32_t GetFlashStartAddress();
    static uint32_t GetFlashEndAddress();
    static uint32_t GetFlashPageSize();
    /// @brief 将先对地址转换为flash地址 [相对地址方式，一般不用]
    /// @param address 
    /// @return 
    static uint32_t ConvertToFlashAddress(uint32_t virual_address);
    static bool CheckFlashAddress(uint32_t address);

private:
    static void TryConvertAddress(uint32_t &address);
    static bool CheckAddressAndLog(uint32_t address);
    static bool CheckBufferLengthAndLog(int length);
    static bool ReadFromFlashImpl(uint32_t address, uint8_t *buffer, int length);
    static bool WriteToFlashImpl(uint32_t address, uint8_t *buffer, int length);
    static bool EraseSector(uint32_t address);

private:
    static uint32_t m_baseAddr;
};

#endif // __SOC_FLASH_H__
